home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Freaks Macintosh Archive
/
Freaks Macintosh Archive.bin
/
Freaks Macintosh Archives
/
Textfiles
/
Hacking
/
UnixCPrograms.sit
/
UnixCPrograms
/
ll.c
< prev
next >
Wrap
Text File
|
1997-02-10
|
15KB
|
608 lines
/*=============================================================*\
* ll.c - link looker *
* Copyright (C) 1994 by The Software System and lilo *
* Written by George Shearer (george@sphinx.biosci.wayne.edu) *
* Cleaned up to usability by lilo. :) *
* *
* September, 1994 - added help, version info and made the *
* program so you can actually use it. :) *
* --lilo *
* *
* October 14, 1994 - cleaned up output flushing so you can *
* actually watch in something like real *
* time. :) --lilo *
* *
* October 28, 1994 - kill -1 will now produce a list of SPLIT *
* servers. -Doc *
* *
* November 4, 1994 - should compile on non-POSIX systems now. *
* use -DHPSUCKS for HP-sUX systems 9.0x *
* November 15, 1994 - fixed a small bug in lilo's -h checker *
\*=============================================================*/
/* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Compiling examples:
regular old ANSI/C cc:
cc -O -s -o ll ll.c
HP-UX cc:
cc +O3 -Aa -s -DHPSUCKS -o ll ll.c
GNU GCC:
Linux:
gcc -O2 -fomit-frame-pointer -funroll-loops -m486 -s -Wall -o ll ll.c
BSD, SunOS 4.1.x, Slowaris 2.x, NeXT:
gcc -O2 -funroll-loops -s -Wall -o ll ll.c */
#define VERSION "1.06"
#define BUFSIZE 400 /* IRC Server buffer */
#define SERVER "dewey.cc.utexas.edu" /* IRC Server */
#define PORT 6667 /* IRC Port */
#define LDELAY 30 /* Loop delay seconds*/
#define TIMEOUT 30 /* connection timeout*/
#define ESTABLISHED 1
#define INPROGRESS 2
#define SPLIT 1
#ifdef HPSUCKS
#define _INCLUDE_HPUX_SOURCE
#define _INCLUDE_XOPEN_SOURCE
#define _INCLUDE_POSIX_SOURCE
#endif
#include <sys/time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <pwd.h>
unsigned short int session=0,link_count=0;
char in[BUFSIZE],out_buf[BUFSIZE],hostname[64];
char *ins=in;
char serverhost[81], nick[10], user[10], realname[81], lasttime[81];
time_t ltime;
struct irc_server {
char *name;
char *link;
unsigned short int status;
time_t time;
struct irc_server *next;
} *sl1=(struct irc_server *)0,*sl2=(struct irc_server *)0;
void do_ping(char *,char *);
void do_001(char *,char *);
void do_error(char *,char *);
void do_364(char *,char *);
void do_365(char *,char *);
/* prototyping is lame when the function is in the same
code, lilo outta just move the function before all
other functions that call it :-) */
char *stamp(time_t);
struct parsers {
char *cmd;
void (*func)(char *,char *);
} parsefuns[] = {
{ "PING", (void (*)())do_ping },
{ "001", (void (*)())do_001 },
{ "364",(void (*)())do_364 },
{ "365", (void (*)())do_365},
{ "ERROR",(void (*)())do_error},
{ (char *)0,(void (*)())0 }
};
struct sockaddr_in server;
int sock=0;
#ifndef sys_errlist
extern char *sys_errlist[];
#endif
#ifndef errno
extern int errno;
#endif
char *
mystrerror(int err) {
return(sys_errlist[err]);
}
unsigned long int
resolver(char *host) {
unsigned long int ip=0L;
if(host && *host && (ip=inet_addr(host))==-1) {
struct hostent *he;
int x=0;
while(!(he=gethostbyname((char *)host)) && x++<3) {
fprintf(stderr,"."); fflush(stderr);
sleep(1);
}
ip=(x<3) ? *(unsigned long *)he->h_addr_list[0] : 0L;
}
return(ip);
}
void
clean_sl2(void) {
while(sl2) {
struct irc_server *temp=sl2->next;
if(sl2->name)
free(sl2->name);
if(sl2->link)
free(sl2->link);
free(sl2);
sl2=temp;
}
sl2=(struct irc_server *)0;
}
void
exit_program(char *why) {
fprintf(stderr,"\nExiting program. (%s)\n",why);
if(sock)
close(sock);
while(sl1) {
struct irc_server *temp=sl1->next;
if(sl1->name)
free(sl1->name);
if(sl1->link)
free(sl1->link);
free(sl1);
sl1=temp;
}
clean_sl2();
if(in)
free(in);
exit(0);
}
int mystrccmp(register char *s1,register char *s2) {
while((((*s1)>='a'&&(*s1)<='z')?(*s1)-32:*s1)==
(((*s2)>='a'&&(*s2)<='z')?(*s2++)-32:*s2++))
if(*s1++==0) return 0;
return (*(unsigned char *)s1-*(unsigned char *)--s2);
}
char *mstrcpy(char **to,char *from) {
if(from) {
if((*to=(char *)malloc(strlen(from)+1)))
strcpy(*to,from);
}
else
*to=(char *)0;
return(*to);
}
char *digtoken(char **string,char *match) {
if(string && *string && **string) {
while(**string && strchr(match,**string))
(*string)++;
if(**string) { /* got something */
char *token=*string;
if((*string=strpbrk(*string,match))) {
*(*string)++=(char)0;
while(**string && strchr(match,**string))
(*string)++;
}
else
*string = ""; /* must be at the end */
return(token);
}
}
return((char *)0);
}
void signal_handler(void) {
exit_program("caught signal");
}
void signal_alarm(void) {
exit_program("timed out waiting for server interaction.");
}
void
out(void) {
int length=strlen(out_buf);
errno=0;
if(write(sock,out_buf,length)!=length)
exit_program(mystrerror(errno));
}
void
init_server(void) {
int length;
sprintf(out_buf,"USER %s %s %s :%s\nNICK %s\nMODE %s +is", \
user, user, user, realname, nick, nick);
length=strlen(out_buf);
errno=0;
if(write(sock,out_buf,length)==length) {
fputs("established\n",stderr);
session=ESTABLISHED;
alarm(TIMEOUT);
sprintf(out_buf,"LINKS\n");
out();
}
else
exit_program(mystrerror(errno));
}
void
heartbeat(void) {
strcpy(out_buf,"LINKS\n");
out();
signal(SIGALRM,(void (*)())heartbeat);
alarm(LDELAY);
}
void
do_364(char *from,char *left) {
struct irc_server *serv;
char *sv1,*sv2;
char *nick;
serv=(struct irc_server *)malloc(sizeof(struct irc_server));
serv->next=sl2;
serv->status=0;
nick=digtoken(&left," ");
sv1=digtoken(&left," ");
sv2=digtoken(&left," ");
mstrcpy(&serv->name,sv1);
mstrcpy(&serv->link,sv2);
sl2=serv;
}
int
findserv(struct irc_server *serv,char *name) {
for(;serv;serv=serv->next)
if(!mystrccmp(name,serv->name))
return(1);
return(0);
}
void
show_split(void) {
struct irc_server *serv=sl1;
signal(SIGHUP,(void (*)())show_split);
for(;serv;serv=serv->next) {
if(serv->status & SPLIT) {
printf("%s SPLIT: %s [%s]\n",stamp(serv->time),serv->name,serv->link);
fflush(stdout);
}
}
}
void
do_365(char *from,char *left) {
struct irc_server *serv=sl1;
for(;serv;serv=serv->next) {
if(!findserv(sl2,serv->name)) {
if(!(serv->status & SPLIT)) {
serv->time=time(NULL);
printf("%s SPLIT: %s [%s]\n",stamp(serv->time),serv->name,serv->link);
fflush(stdout);
serv->status|=SPLIT;
}
}
else
if(serv->status & SPLIT) {
serv->time=time(NULL);
printf("%s MERGE: %s [%s]\n",stamp(serv->time),serv->name,serv->link);
fflush(stdout);
serv->status&=~SPLIT;
}
}
serv=sl2;
for(;serv;serv=serv->next) {
if(!findserv(sl1,serv->name)) {
struct irc_server *serv2;
serv2=(struct irc_server *)malloc(sizeof(struct irc_server));
serv2->next=sl1;
serv2->status=0;
mstrcpy(&serv2->name,serv->name);
mstrcpy(&serv2->link,serv->link);
sl1=serv2;
serv2->time=time(NULL);
if(link_count) {
printf("%s ADDED: %s [%s]\n",stamp(serv2->time),serv->name,serv->link);
fflush(stdout);
}
}
}
link_count=1;
clean_sl2();
}
void
do_ping(char *from,char *left) {
sprintf(out_buf,"PING :%s\n",hostname);
out();
}
void
do_001(char *from,char *left) {
fprintf(stderr,"Logged into server %s as nickname %s\n\n",from,nick);
fflush(stderr);
alarm(0);
signal(SIGALRM,(void (*)())heartbeat);
alarm(LDELAY);
}
void
do_error(char *from,char *left) {
fprintf(stderr,"Server error: %s\n",left);
fflush(stderr);
}
void
parse2(void) {
char *from,*cmd,*left;
if(*ins==':') {
if(!(cmd=strchr(ins,' ')))
return;
*cmd++=(char)0;
from=ins+1;
}
else {
cmd=ins;
from=(char *)0;
}
if((left=strchr(cmd,' '))) {
int command;
*left++=(char)0;
left=(*left==':') ? left+1 : left;
for(command=0;parsefuns[command].cmd;command++) {
if(!mystrccmp(parsefuns[command].cmd,cmd)) {
parsefuns[command].func(from,left);
break;
}
}
}
}
void
parse(int length) {
char *s=in;
*(ins+length)=(char)0;
for(;;) {
ins=s;
while(*s && *s!=(char)13 && *s!=(char)10)
s++;
if(*s) {
while(*s && (*s==(char)13 || *s==(char)10))
*s++=(char)0;
parse2();
}
else
break;
}
strcpy(in,ins);
ins=in+(s-ins);
}
void
process_server(void) {
int x=0;
for(;;) {
fd_set rd,wr;
struct timeval timeout;
timeout.tv_usec=0; timeout.tv_sec=1;
FD_ZERO(&rd); FD_ZERO(&wr);
FD_SET(sock,&rd);
if(session==INPROGRESS)
FD_SET(sock,&wr);
errno=0;
#ifdef HPSUCKS
select((size_t)FD_SETSIZE,(int *)&rd,(int *)&wr,(int *)0,(session==INPROGRESS)?(const struct timeval *)&timeout:(const struct timeval *)0);
#else
select(getdtablesize(),(fd_set *)&rd,(fd_set *)&wr,(fd_set *)0,(session==INPROGRESS)?(struct timeval *)&timeout:(struct timeval *)0);
#endif
if(errno==EINTR)
continue;
errno=0;
if(session==INPROGRESS) {
if(FD_ISSET(sock,&wr)) {
init_server();
continue;
}
else {
if(x++>=TIMEOUT)
exit_program("connection timed out");
fprintf(stderr,"."); fflush(stderr);
}
}
if(FD_ISSET(sock,&rd)) {
int length=read(sock,ins,BUFSIZE-(ins-in));
if(length<1) {
if(session!=INPROGRESS) {
if(!errno) {
fputs("Connection closed by foreign host.",stderr);
errno=ENOTCONN;
}
else
fprintf(stderr,"Connection to %s closed.\n",
inet_ntoa(server.sin_addr));
fflush(stderr);
}
exit_program(mystrerror(errno));
}
if(strpbrk(in,"\x0a\x0d"))
parse(length);
else
ins=(BUFSIZE-((ins+length)-in)<1)?in:ins+length;
}
}
}
char *stamp(time_t ltime) {
strftime(lasttime, 81, "%x %X", localtime(<ime));
return (char *) &lasttime;
}
void
main(int argc,char *argv[]) {
unsigned short int sport=PORT;
unsigned int loop;
struct passwd *passent;
fprintf(stderr, "Link Looker v%s, written and designed by Dr. Delete.\n" \
" Enhanced by lilo.\n" \
"Type '%s -h' or '%s --help' for more information.\n\n",
VERSION, argv[0], argv[0]);
for(loop=1; loop<argc; loop++) {
if(!strcmp("-h", argv[loop]) || !strcmp("--help", argv[loop])) {
fprintf(stderr,"Format:\n\n" \
" %s [-h] [<nick> [<server>[:<port>] ['<real name field>' " \
"[<username>]]]]\n\n where:\n\n" \
" <nick> is the nickname to be used (default is userid),\n" \
" <server> is the hostname of the server to be used,\n" \
" <port> is a four digit port number (default is 6667),\n" \
" <real name field> is a description of the user (default is gecos info), and\n" \
" <username> is the user account field, used only if identd\n" \
" has not been enabled on the user's system.\n", \
argv[0]);
exit(1);
}
}
passent=getpwuid(getuid());
if(argc>1)
strncpy(nick,argv[1],9);
else
strncpy(nick,passent->pw_name,9);
if(argc>2) {
char *port=strchr(argv[2],':');
sport=(port)?atoi(port+1):sport;
strncpy(serverhost,argv[2],80);
if(port)
serverhost[port-argv[2]]=(char)0;
}
else
strncpy(serverhost,SERVER,80);
if(argc>3)
strncpy(realname,argv[3],80);
else {
char *comma=strchr(passent->pw_gecos,',');
strncpy(realname,passent->pw_gecos,80);
if(comma)
realname[comma-(passent->pw_gecos)]=(char)0;
}
if(argc>4)
strncpy(user,argv[4],9);
else
strncpy(user,passent->pw_name,9);
signal(SIGPIPE,(void (*)())signal_handler);
signal(SIGHUP,(void (*)())show_split);
signal(SIGINT,(void (*)())signal_handler);
signal(SIGTERM,(void (*)())signal_handler);
signal(SIGBUS,(void (*)())signal_handler);
signal(SIGABRT,(void (*)())signal_handler);
signal(SIGSEGV,(void (*)())signal_handler);
signal(SIGALRM,(void (*)())signal_alarm);
errno=0;
if((sock=socket(AF_INET,SOCK_STREAM,0))>0) {
server.sin_family=AF_INET;
server.sin_port=htons(sport);
fprintf(stderr,"Resolving %s...",serverhost); fflush(stderr);
if((server.sin_addr.s_addr=resolver(serverhost))) {
fputs("done\n",stderr);
fflush(stderr);
setsockopt(sock,SOL_SOCKET,SO_LINGER,0,0);
setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,0,0);
setsockopt(sock,SOL_SOCKET,SO_KEEPALIVE,0,0);
fcntl(sock,F_SETFL,(fcntl(sock,F_GETFL)|O_NDELAY));
fprintf(stderr,"Connecting to %s...",inet_ntoa(server.sin_addr));
fflush(stderr);
errno=0;
if(connect(sock,(struct sockaddr *)&server,sizeof(server))) {
if(errno!=EINPROGRESS && errno!=EWOULDBLOCK)
exit_program(mystrerror(errno));
else
session=INPROGRESS;
}
else
init_server();
gethostname(hostname,64);
process_server();
}
else
exit_program("resolve failed");
}
else {
fprintf(stderr,"Failed to allocate an AF_INET socket. (%s)\n", \
mystrerror(errno));
fflush(stderr);
}
}